programming4us
           
 
 
Programming

.NET Components : Custom Serialization (part 1) - The ISerializable Interface, Implementing ISerializable

- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019
6/30/2013 9:22:02 PM

Sometimes, the default automatic serialization provided by the Serializable attribute is insufficient. Perhaps the object state contains sensitive information, such as a credit card number. In that case, you may want to encrypt the state instead of using a plain by-value serialization. Some other examples that might require custom serialization solutions are if you have some internal knowledge of how to serialize the event subscribers, if which members get serialized depends on the state of the object, or if you want to perform additional proprietary initialization steps during deserialization.

1. The ISerializable Interface

.NET provides an easy-to-use mechanism for custom serialization that extends the serialization infrastructure. To provide custom serialization and deserialization behavior, you need to implement the ISerializable interface, defined in the System.Runtime.Serialization namespace:

    public interface ISerializable
    {
       void GetObjectData(SerializationInfo info,StreamingContext context);
    }

Every time a client serializes an object, .NET reflects the object's metadata to see whether the serializable object implements ISerializable. If it does, .NET calls GetObjectData( ) to retrieve the object's state. At this point, it's up to the object to provide the state information in whichever way it wants. You will see an example of implementing ISerializable shortly.

To support the matching custom deserialization, the object must provide a special parameterized custom deserialization constructor with this signature:

    <Class Name>(SerializationInfo info,StreamingContext context);

.NET calls this constructor during deserialization. The constructor can (and should) be defined as protected to prevent normal clients from calling it. .NET uses reflection to invoke the custom deserialization constructor and thus isn't impeded by the constructor being protected. If the class implements the ISerializable interface but doesn't provide a custom deserialization constructor, the compiler doesn't warn you. Instead, during deserialization, .NET throws an exception of type SerializationException.

In .NET, interfaces aren't allowed to have any implementation details and therefore can't define constructors. The design decision the architects of .NET serialization took was to force a runtime check for the custom deserialization constructor, instead of a compile-time check. However, I believe a better design decision would have been to provide a SetObjectData( ) method on ISerializable and, during deserialization, to use reflection to set the fields of a new object.


Note that the client isn't required to treat an object that implements ISerializable any differently from an object that uses automatic serialization. Custom serialization is purely a component-side facility. The client uses the formatters and streams, as with automatic serialization.

2. Implementing ISerializable

Both GetObjectData( ) and the custom deserialization constructor accept a parameter of type SerializationInfo called info. SerializationInfo provides methods for getting or adding field values. Each field is identified by a string. Because SerializationInfo was defined before generics were available, SerializationInfo has type-safe methods for most of the CLR-defined types, such as int and string. For each such type, SerializationInfo provides two methods in this form:

    void AddValue(string name, <Type> value);
    <Type> Get<Type>(string name);

Here's an example:

    public sealed class SerializationInfo
    {
       public void AddValue(string name, short value);
       public void AddValue(string name, int value);
       //Other AddValue(  ) methods

       public int    GetInt32(string name);
       public string GetString(string name);
       //Other Get<Type>(  ) methods

       //Other methods and properties
    }

For all other field types, SerializationInfo provides methods like these to add or get an object:

    public void AddValue(string name, object value);
    public object GetValue(string name, Type type);

The second parameter that both GetObjectData( ) and the custom deserialization constructor accept is the context parameter, of type StreamingContext. Example 1 demonstrates both ISerializable and the custom deserialization constructor. The way the class in Example 9-15 implements custom serialization has no advantage over automatic serialization; it simply shows how to provide custom serialization. It's up to you to provide the required custom steps.

Example 1. Implementing ISerializable
						[Serializable]
public class MyClass : ISerializable
{
   int m_Number;
   string m_SomeString;
   public virtual void GetObjectData(SerializationInfo info,
                                     StreamingContext context)
   {
      info.AddValue("m_Number",m_Number);
      info.AddValue("m_SomeString",m_SomeString);
   }
   protected MyClass(SerializationInfo info,StreamingContext context)
   {
      m_Number = info.GetInt32("m_Number");
      m_SomeString = info.GetString("m_SomeString");
   }

   public MyClass(  )
   {}
}

When you implement ISerializable, the type must still be decorated with the Serializable attribute. Otherwise, .NET considers the type non-serializable and ignores ISerializable.


If the serialized class is a generic class, you need to use the AddValue( ) and GetValue( ) methods that accept an object while specifying the type, as shown in Example 2.

Example 2. Custom serialization of a generic class
[Serializable]
public class MyClass<T> : ISerializable
{
   T m_T;
   public MyClass(  )
   {}
   public void GetObjectData(SerializationInfo info,StreamingContext ctx)
   {
      info.AddValue("m_T",m_T,typeof(T));
   }
   protected MyClass(SerializationInfo info,StreamingContext context)
   {
      m_T = (T)info.GetValue("m_T",typeof(T));
   }
}

2.1. GenericSerializationInfo

The introduction of generics in .NET 2.0 allows you to improve on the available SerializationInfo and shield the client code from the type retrieval and explicit casting.

Example 3 presents the GenericSerializationInfo utility class, which exposes generic AddValue( ) and GetValue( ) methods. GenericSerializationInfo encapsulates a regular SerializationInfo object, passed to it as a construction parameter.

Example 3. The GenericSerializationInfo utility class
public class GenericSerializationInfo
{
   SerializationInfo m_SerializationInfo;
   public GenericSerializationInfo(SerializationInfo info)
   {
      m_SerializationInfo = info;
   }
   public void AddValue<T>(string name,T value)
   {
      m_SerializationInfo.AddValue(name,value,value.GetType(  ));

   }
   public T GetValue<T>(string name)
   {
      object obj = m_SerializationInfo.GetValue(name,typeof(T));
      return (T)obj;
   }
}

Example 4 shows the same custom serialization code as Example 9-16, except it uses GenericSerializationInfo. Note the use of type inference in the call to AddValue( ).

Example 4. Using GenericSerializationInfo
[Serializable]
public class MyClass<T> : ISerializable
{
   T m_T;
   public MyClass(  )
   {}
   public void GetObjectData(SerializationInfo info,StreamingContext ctx)
   {
      GenericSerializationInfo genericInfo = new GenericSerializationInfo(info);
      genericInfo.AddValue("m_T",m_T); //Using type inference
   }
   protected MyClass(SerializationInfo info,StreamingContext context)
   {
      GenericSerializationInfo genericInfo = new GenericSerializationInfo(info);
      m_T = genericInfo.GetValue<T>("m_T");
   }
}

					  

GenericSerializationInfo is a cleaner way of using custom serialization, even on non-generic-type class members. For example, using GenericSerializationInfo in the class MyClass from Example 1, you could write:

    genericInfo.AddValue("m_SomeString",m_SomeString);

and:

    m_SomeString = genericInfo.GetValue<string>("m_SomeString");

2.2. Custom serialization and IDeserializationCallback

Implementing IDeserializationCallback allows a type to be notified after deserialization takes place and to perform additional, custom deserialization steps. You can implement both IDeserializationCallback and ISerializable, but when you implement ISerializable there is really no need for IDeserializationCallback, because you can place the custom steps in the custom deserialization constructor.

2.3. Custom serialization and serialization events

It is technically possible to use the serializing and deserializing events for custom serialization and avoid implementing ISerializable; however, this will come at a high price in programming model and code readability and maintainability. You will need to have a separate set of member variables, all marked as non-serializable. The type itself will use those members, and the serialization events will perform the custom steps (such as encryption or decryption) on the non-serializable members and then copy them to the set of serializable member variables, whose sole purpose will be to be serialized and deserialized. Needless to say, such an approach is cumbersome and error-prone. It is better to stick with the dedicated ISerializable standard mechanism.

Other -----------------
- .NET Components : Serialization and Streams - Serializing Multiple Objects
- Microsoft ASP.NET 3.5 : Writing HTTP Handlers (part 5) - Advanced HTTP Handler Programming
- Microsoft ASP.NET 3.5 : Writing HTTP Handlers (part 4) - Serving Images More Effectively
- Microsoft ASP.NET 3.5 : Writing HTTP Handlers (part 3) - The Picture Viewer Handler
- Microsoft ASP.NET 3.5 : Writing HTTP Handlers (part 2) - An HTTP Handler for Quick Data Reports
- Microsoft ASP.NET 3.5 : Writing HTTP Handlers (part 1) - The IHttpHandler Interface
- Microsoft ASP.NET 3.5 : HTTP Handlers and Modules - Quick Overview of the IIS Extensibility API
- Programming WCF Services : Queued Services - The HTTP Bridge
- Microsoft ASP.NET 4 : Ajax - Extender Controls (part 2) - A Modal Pop-up Dialog-Style Component
- Microsoft ASP.NET 4 : Ajax - Extender Controls (part 1) - The AutoComplete Extender
- Mobile Handheld Devices : DATA SYNCHRONIZATION
- Mobile Handheld Devices : MEMORY, STORAGE AND BATTERIES
- LINQ to Objects : How to Return Elements When the Result Is a Sequence (Select Many)
- LINQ to Objects : How to Change the Return Type (Select Projection)
- A Technical Overview of the Mobile Web : OTHER MOBILE TECHNOLOGIES
- A Technical Overview of the Mobile Web : THE MOBILE NETWORK
- Programming WCF Services : The Response Service (part 4) - Transactions
- Programming WCF Services : The Response Service (part 3) - Queued Service-Side Programming & Response Service-Side Programming
- Programming WCF Services : The Response Service (part 2) - Client-Side Programming
- Programming WCF Services : The Response Service (part 1) - Designing a Response Service Contract
 
 
 
Top 10
 
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
- First look: Apple Watch

- 3 Tips for Maintaining Your Cell Phone Battery (part 1)

- 3 Tips for Maintaining Your Cell Phone Battery (part 2)
programming4us programming4us